#ifndef __M_SERVER_H__
#define __M_SERVER_H__

#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <string>
#include <sys/epoll.h>
#include <vector>
#include <unordered_map>
#include <cstring>
#include <sys/eventfd.h>
#include <thread>
#include <mutex>
#include <memory>
#include <functional>
#include <sys/timerfd.h>
#include <condition_variable>
#include "any.hpp"
#include "Buffer.hpp"
#include "../logs/log.h"

namespace Muduo
{
    const int MAX_LISTEN = 1024;
    class Socket
    {
    public:
        Socket()
            : _sockfd(-1)
        {
        }
        Socket(int fd)
            : _sockfd(fd)
        {
        }
        ~Socket()
        {
            Close();
        }
        int Fd()
        {
            return _sockfd;
        }
        // 创建套接字
        bool Create()
        {
            _sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
            if (_sockfd < 0)
            {
                LOGERROR("socket create fail!");
                return false;
            }
            return true;
        }
        // 绑定地址信息(绑定套接字)
        bool Bind(uint16_t port, const std::string &ip)
        {
            struct sockaddr_in addr;
            addr.sin_family = AF_INET;
            addr.sin_port = htons(port);
            addr.sin_addr.s_addr = inet_addr(ip.c_str());
            socklen_t len = sizeof(addr);
            int ret = bind(_sockfd, (struct sockaddr *)&addr, len);
            if (ret < 0)
            {
                LOGERROR("bind addr fail!");
                return false;
            }
            return true;
        }
        // 开始监听
        bool Listen(int backlog = MAX_LISTEN)
        {
            int ret = listen(_sockfd, backlog);
            if (ret < 0)
            {
                LOGERROR("listen socket fail!");
                return false;
            }
            return true;
        }
        // 向服务器发起连接
        bool Connect(uint16_t port, const std::string &ip)
        {
            struct sockaddr_in addr;
            addr.sin_family = AF_INET;
            addr.sin_port = htons(port);
            addr.sin_addr.s_addr = inet_addr(ip.c_str());
            socklen_t len = sizeof(addr);
            int ret = connect(_sockfd, (struct sockaddr *)&addr, len);
            if (ret < 0)
            {
                LOGERROR("connect server fail!");
                return false;
            }
            return true;
        }
        // 获取连接
        int Accept()
        {
            int newfd = accept(_sockfd, nullptr, nullptr);
            if (newfd < 0)
            {
                LOGERROR("socket accept fail!");
                return -1;
            }
            return newfd;
        }
        // 接收数据
        ssize_t Recv(void *buf, size_t len, int flag = 0)
        {
            ssize_t ret = recv(_sockfd, buf, len, flag);
            if (ret <= 0)
            {
                // EAGAIN表示当前socket的接收缓冲区中没有数据了，在非阻塞情况下才会有这个错误；
                // EINTR表示当前socket的阻塞等待被信号打断了；
                if (errno == EAGAIN || errno == EINTR)
                {
                    return 0; // 表示没有接收到数据
                }
                LOGERROR("socket recv fail!");
                return -1;
            }
            return ret; // 实际接收的数据长度
        }
        // 非阻塞接收数据
        ssize_t NonBlockRecv(void *buf, size_t len)
        {
            return Recv(buf, len, MSG_DONTWAIT); // MSG_DONTWAIT表示当前接收为非阻塞状态
        }
        // 发送数据
        ssize_t Send(void *buf, size_t len, int flag = 0)
        {
            ssize_t ret = send(_sockfd, buf, len, flag);
            if (ret < 0)
            {
                // EAGAIN表示当前socket的发送缓冲区中数据满了，在非阻塞情况下才会有这个错误；
                // EINTR表示当前socket的阻塞等待被信号打断了；
                if (errno == EAGAIN || errno == EINTR)
                {
                    return 0; // 表示没有任何数据被发送出去
                }
                LOGERROR("send data fail!");
                return -1;
            }
            // printf("ret:%d\n",ret);
            return ret; // 实际发送数据的长度
        }
        // 非阻塞发送数据
        ssize_t NonBlockSend(void *buf, size_t len)
        {
            if(len == 0)
            {
                return 0;
            }
            return Send(buf, len, MSG_DONTWAIT); // MSG_DONTWAIT表示当前发送为非阻塞状态
        }
        // 关闭套接字
        void Close()
        {
            if (_sockfd != -1)
            {
                // printf("关闭文件描述符\n");
                close(_sockfd);
                _sockfd = -1;
            }
        }
        // 创建一个监听套接字
        bool CreateListenSocket(uint16_t port, const std::string &ip = "0.0.0.0", bool block_flag = false)
        {
            //地址复用要在bind的绑定地址信息的前面，否则会出现服务器主动断开连接后，套接字进入TIME_WAIT状态后，无法立即被绑定的问题
            // 1.创建套接字；2.设置为非阻塞；3.绑定地址；4.开始监听；5.启动地址重用
            if (Create() == false)
                return false;
            if (block_flag)
                NonBlock();
            ReuseAddress();//先设置地址复用再bind绑定地址信息
            if (Bind(port, ip) == false)
                return false;
            if (Listen() == false)
                return false;
            return true;
        }
        // 创建一个客户端连接
        bool CreateClientSocket(uint16_t port, const std::string &ip)
        {
            // 1.创建套接字；2.向服务器发起连接;
            if (Create() == false)
                return false;
            if (Connect(port, ip) == false)
                return false;
            return true;
        }
        // 设置套接字选项---开启地址端口重用
        void ReuseAddress()
        {
            int val = 1;
            setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(int)); // 地址重用
            val = 1;
            setsockopt(_sockfd, SOL_SOCKET, SO_REUSEPORT, (void *)&val, sizeof(int)); // 端口重用
        }
        // 设置套接字阻塞属性---设置为非阻塞
        void NonBlock()
        {
            // 先获取套接字中原有的属性，如果不先获取直接设置的话会将套接字中原有的属性给覆盖掉，是不合理的；
            int flag = fcntl(_sockfd, F_GETFL, 0);      // F_GETFL表示获取文件描述符的属性，获取的属性通过返回值返回
            fcntl(_sockfd, F_SETFL, flag | O_NONBLOCK); // F_SETFL表示设置文件描述符的属性，要设置的属性通过第三个参数传递
        }
    private:
        int _sockfd;
    };

    class EventLoop;
    class Channel
    {
        using EventCallback = std::function<void()>;
    public:
        Channel(int fd, Muduo::EventLoop *loop)
            : _fd(fd), _events(0), _revents(0), _loop(loop)
        {
        }
        ~Channel()
        {
            _readCallback = nullptr;
            _writeCallback = nullptr; // 可写事件回调函数
            _errorCallback = nullptr; // 错误事件回调函数
            _closeCallback = nullptr; // 关闭连接事件回调函数
            _eventCallback = nullptr; // 任意事件回调函数
        }
        // 获取事件的接口
        uint32_t Events()
        {
            return _events;
        }
        // 获取描述符的接口
        int Fd()
        {
            return _fd;
        }
        // 1.事件管理
        //  当前是否监控了可读
        bool ReadAble()
        {
            return (_events & EPOLLIN);
        }
        // 当前是否监控了可写
        bool WriteAble()
        {
            return (_events & EPOLLOUT);
        }
        // 启动读事件监控
        void EnableRead()
        {
            _events |= EPOLLIN;
            // done---还要添加到EventLoop模块的事件监控中
            Update();
        }
        // 启动写事件监控
        void EnableWrite()
        {
            _events |= EPOLLOUT;
            // done---还要添加到EventLoop模块的事件监控中
            Update();
        }
        // 关闭读事件监控
        void DisableRead()
        {
            _events &= ~EPOLLIN;
            // done---还要解除EventLoop模块中该事件的监控
            Update();
        }
        // 关闭写事件监控
        void DisableWrite()
        {
            _events &= ~EPOLLOUT;
            // done---还要解除EventLoop模块中该事件的监控
            Update();
        }
        // 关闭所有事件的监控
        void DisableAll()
        {
            _events = 0;
            Update();
        }
        // 将当前连接的事件监控从epoll中移除
        void Remove();
        // 将事件监控更新到epoll模型中
        void Update();

        // 2. 事件触发后的处理管理
        // 设置可读事件触发后的回调函数
        void SetReadCallback(const EventCallback &cb)
        {
            _readCallback = cb;
        }
        // 设置可写事件触发后的回调函数
        void SetWriteCallback(const EventCallback &cb)
        {
            _writeCallback = cb;
        }
        // 设置错误事件触发后的回调函数
        void SetErrorCallback(const EventCallback &cb)
        {
            _errorCallback = cb;
        }
        // 设置关闭连接事件触发后的回调函数
        void SetCloseCallback(const EventCallback &cb)
        {
            _closeCallback = cb;
        }
        // 设置任意事件触发后的回调函数
        void SetEventCallback(const EventCallback &cb)
        {
            _eventCallback = cb;
        }
        // 设置已经触发的事件
        void SetRevents(uint32_t events)
        {
            _revents = events;
        }

        // 事件处理函数---一旦连接触发了事件，就调用这个函数，在这个函数中判断那个事件触发了并调用对应的回调函数
        void HandleEvent()
        {
            if ((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI))
            {

                if (_readCallback)
                {
                    _readCallback();
                }
            }
            // 有可能会释放连接的操作，一次只处理一个，比如一个连接上写入数据的时候出错了，将连接释放了，就不应该再去处理该连接上的错误事件了；
            if (_revents & EPOLLOUT)
            {                
                if (_writeCallback)
                {
                    _writeCallback();
                }
            }
            else if (_revents & EPOLLERR)
            {
                if (_errorCallback) // 一旦出错，就会释放连接，因此要放到全部调用任意回调
                {
                    _errorCallback();
                }
            }
            else if (_revents & EPOLLHUP)
            {
                if (_closeCallback) // 一旦出错，就会释放连接，因此要放到全部调用任意回调
                {
                    _closeCallback();
                }
            }
            if (_eventCallback)
            {
                _eventCallback();
            }
        }

    private:
        int _fd;                      // 要进行事件管理的文件描述符
        uint32_t _events;             // 需要监控的事件
        uint32_t _revents;            // 已经触发的事件
        Muduo::EventLoop *_loop;      // 事件监控模块
        EventCallback _readCallback;  // 可读事件回调函数
        EventCallback _writeCallback; // 可写事件回调函数
        EventCallback _errorCallback; // 错误事件回调函数
        EventCallback _closeCallback; // 关闭连接事件回调函数
        EventCallback _eventCallback; // 任意事件回调函数
    };

    const size_t MAX_EPOLLEVENTS = 1024;
    class Poller
    {
    private:
        // 针对epoll直接操作(添加，修改，移除)
        void Update(Muduo::Channel *channel, int opt)
        {
            int fd = channel->Fd();
            struct epoll_event event;
            event.data.fd = fd;
            event.events = channel->Events();
            int ret = epoll_ctl(_epfd, opt, fd, &event);
            if (ret < 0)
            {
                LOGERROR("epollctl fail!");
                abort();
            }
        }
        // 判断要更新的描述符是否存在
        bool HasChannel(Muduo::Channel *channel)
        {
            auto it = _channels.find(channel->Fd());
            if (it == _channels.end())
            {
                return false;
            }
            return true;
        }

    public:
        Poller()
            : _events(MAX_EPOLLEVENTS)
        {
            _epfd = epoll_create(1);
            if (_epfd < 0)
            {
                LOGERROR("epoll create fail!");
                abort();
            }
        }
        ~Poller()
        {
            if (_epfd > 0)
            {
                close(_epfd);
            }
        }

        // 添加/修改描述符的事件监控(不存在则添加，存在则修改)
        void UpdateEvent(Muduo::Channel *channel)
        {
            if (channel == nullptr)
            {
                LOGERROR("channel ptr is nullptr!");
                return;
            }
            bool ret = HasChannel(channel);
            if (ret == false)
            {
                // 不存在就添加事件的监控, 并添加到_channels哈希表中
                Update(channel, EPOLL_CTL_ADD);
                _channels[channel->Fd()] = channel;
            }
            else
            {
                // 存在则修改事件监控
                Update(channel, EPOLL_CTL_MOD);
            }
        }
        // 移除描述符的事件监控
        void ReMoveEvent(Muduo::Channel *channel)
        {
            bool ret = HasChannel(channel);
            if (ret)
            {
                // 有事件监控才可以移除
                Update(channel, EPOLL_CTL_DEL);
                auto it = _channels.find(channel->Fd());
                if (it != _channels.end())
                {
                    _channels.erase(it);
                }
            }
            else
            {
                LOGERROR("fd is not epoll!");
                return;
            }
        }
        // 开始监控，通过输出型参数返回活跃连接
        void Poll(std::vector<Muduo::Channel *> &active)
        {
            int nfds = epoll_wait(_epfd, &_events[0], MAX_EPOLLEVENTS, -1);
            if (nfds < 0)
            {
                // EINTR表示阻塞状态被信号打断了
                if (errno == EINTR)
                {
                    return;
                }
                LOGERROR("epoll wait error: %s", strerror(errno));
                abort();
            }
            for (int i = 0; i < nfds; ++i)
            {
                auto it = _channels.find(_events[i].data.fd);
                if (it == _channels.end())
                {
                    exit(-1);
                }
                // 设置描述符上实际就绪的事件
                it->second->SetRevents(_events[i].events);
                active.push_back(it->second);
            }
        }

    private:
        int _epfd;                                           // epoll模型对应的fd
        std::vector<struct epoll_event> _events;             // 在事件监控的时候用于保存所有的活跃事件
        std::unordered_map<int, Muduo::Channel *> _channels; // 将描述符和对应的Channel对象映射起来
    };

    const int defaultCapacity = 60;
    using TaskFunc = std::function<void()>;
    using ReleaseFunc = std::function<void()>;
    class EventLoop;
    // 定时器任务类
    class TimerTask
    {
    public:
        TimerTask(uint64_t id, uint32_t delay, const TaskFunc &taskCb)
            : _id(id), _timeout(delay), _taskCb(taskCb), _canceled(false)
        {
        }
        // 析构函数中执行定时任务，执行定时任务后回调删除TimerWheel中保存的定时器对象的回调函数
        ~TimerTask()
        {
            if (_canceled == false)
                _taskCb();
            _release();
        }
        // 设置删除Timerwheel中保存的定时器对象信息的回调函数
        void SetRelease(const ReleaseFunc &cb)
        {
            _release = cb;
        }
        uint32_t Timeout()
        {
            return _timeout;
        }
        // 取消定时任务
        void Cancel()
        {
            _canceled = true;
        }

    private:
        uint64_t _id;   // 定时器任务对象的id:
        uint32_t _timeout;    // 定时器任务的超时时间：
        bool _canceled;       // false表示没有被取消，true表示被取消：
        TaskFunc _taskCb;     // 定时器任务要执行的定时任务：
        ReleaseFunc _release; // 用于删除TimerWheel中保存的定时器对象信息;
    };
    // 时间轮
    class TimerWheel
    {
    private:
        using PtrTask = std::shared_ptr<TimerTask>;
        using WeakTask = std::weak_ptr<TimerTask>;
        // 移除TimerWheel中保存的定时器对象信息
        void RemoveTimers(uint64_t id)
        {
            auto it = _timers.find(id);
            if (it == _timers.end())
            {
                LOGERROR("_timers 中没有保存定时器对象的信息！");
                return;
            }
            _timers.erase(id);
        }
        //创建一个定时器文件描述符
        static int CreateTimerfd()
        {
            int timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
            if (timerfd < 0)
            {
                LOGERROR("timerfd create fail!");
                abort();
            }
            struct itimerspec itime;
            itime.it_value.tv_sec = 1;
            itime.it_value.tv_nsec = 0; // 第一次超时时间为1s后
            itime.it_interval.tv_sec = 1;
            itime.it_interval.tv_nsec = 0; // 第一次超时后，每次超时的间隔时间为1s
            timerfd_settime(timerfd, 0, &itime, nullptr);
            return timerfd;
        }
        //读取定时器文件描述符中的数据---也就是获取定时器的超时次数
        int ReadTimerfd()
        {
            uint64_t times;
            //有可能因为其他描述符的事件处理花费时间比较长，然后在处理定时器描述符事件的时候，有可能就已经超时了很多次
            //read读到的数据times就是从上一次read之后超时的次数
            int ret = read(_timerfd, &times, 8);
            if (ret < 0)
            {
                LOGERROR("timerfd read fail!");
                abort();
            }
            return times;
        }

        // 往时间轮中添加定时器任务类---在任何一个线程中都有可能添加定时任务，但是定时器是和EventLoop绑定在一起的，很多任务都是对连接进行操作的
        // 所以定时任务必须在EventLoop对应的线程中执行的
        void TimerAddInLoop(uint64_t id, uint32_t delay, TaskFunc taskCb)
        {
            PtrTask pt(new TimerTask(id, delay, taskCb));
            pt->SetRelease(std::bind(&Muduo::TimerWheel::RemoveTimers, this, id));
            WeakTask wt(pt);
            int pos = (_tick + delay) % _capacity;
            _wheel[pos].push_back(pt);
            _timers[id] = wt;
        }

        // 刷新/延迟定时任务
        void TimerRefreshInLoop(uint64_t id)
        {
            // 通过保存在定时器任务对象的weak_ptr构造一个shared_ptr出来，添加到时间轮中
            auto it = _timers.find(id);
            if (it == _timers.end())
            {
                LOGERROR("_timers 中没有保存定时器对象的信息！");
                return; // 没有找到定时器任务对象
            }
            PtrTask pt = it->second.lock();
            uint32_t delay = pt->Timeout();
            int pos = (_tick + delay) % _capacity;
            _wheel[pos].push_back(pt);
        }

        // 取消定时任务
        void TimerCancelInLoop(uint64_t id)
        {
            auto it = _timers.find(id);
            if (it == _timers.end())
            {
                LOGERROR("_timers 中没有保存定时器对象的信息！");
                return;
            }
            PtrTask pt = it->second.lock();
            if (pt)
            {
                pt->Cancel();
            }
        }

        //_tick指针每走到一个位置就运行该位置的定时任务
        void RunTimerTask()
        {
            _tick = (_tick + 1) % _capacity;
            //vector容器的clear函数会调用每个元素的析构函数
            _wheel[_tick].clear(); // 清空指定位置的数组，就会把数组中保存的所有管理定时器对象的shared_ptr释放掉；
        }
    public:
        TimerWheel(Muduo::EventLoop *loop, int capacity = defaultCapacity)
            : _timerfd(CreateTimerfd()),
              _loop(loop),
              _timerChannel(new Muduo::Channel(_timerfd, _loop)),
              _tick(0), _capacity(capacity),
              _wheel(capacity)
        {
            // 设置定时器描述符的事件和回调函数
            _timerChannel->SetReadCallback(std::bind(&TimerWheel::OnTime, this));
            _timerChannel->EnableRead(); // 启动定时器描述符的读事件监控；
        }
        ~TimerWheel() {}
        // 定时器中有个_timers成员，定时器信息的操作有可能在多个线程中进行，因此需要考虑线程安全问题
        // 如果不想加锁，就将所有对定时器的操作都放到同一个线程中来完成，保证了线程安全；
        void TimerAdd(uint64_t id, uint32_t delay, TaskFunc taskCb);
 
        // 定时器中有个_timers成员，定时器信息的操作有可能在多个线程中进行，因此需要考虑线程安全问题
        // 如果不想加锁，就将所有对定时器的操作都放到同一个线程中来完成，保证了线程安全；
        void TimerRefresh(uint64_t id);

        // 定时器中有个_timers成员，定时器信息的操作有可能在多个线程中进行，因此需要考虑线程安全问题
        // 如果不想加锁，就将所有对定时器的操作都放到同一个线程中来完成，保证了线程安全；
        void TimerCancel(uint64_t id);

        // 定时器的1s钟时间到了，需要读取定时器并执行_tick指针位置的定时任务
        void OnTime()
        {
            int times = ReadTimerfd();
            //根据实际超时次数，执行对应的超时任务
            while(times--)
            {
                RunTimerTask();
            }
        }

        //判断是否有某个定时任务---存在线程安全问题，只能在对应的EventLoop线程内调用
        bool HasTimer(uint64_t id)
        {
            auto it = _timers.find(id);
            if (it == _timers.end())
            {
                return false;
            }
            return true;
        }

    private:
        int _timerfd;                                   // 定时器描述符
        Muduo::EventLoop *_loop;                        // 对定时器描述符进行事件监控监控和事件处理
        std::unique_ptr<Muduo::Channel> _timerChannel;  // 对定时器描述符进行事件监控的管理
        int _tick;                                      // 指针--当前指针，走到哪里就释放哪里，释放哪里就相当于执行的定时任务
        int _capacity;                                  // 时间轮的大小-表盘的最大数量，也就是最大延迟时间：
        std::vector<std::vector<PtrTask>> _wheel;       // 时间轮数组
        std::unordered_map<uint64_t, WeakTask> _timers; // 让定时器任务的id和添加到任务队列中的任务进行映射，便于查找：
    };

    class EventLoop
    {
        using Functor = std::function<void()>;
    public:
        EventLoop()
            : _threadId(std::this_thread::get_id()),
              _eventFd(CreateEventFd()),
              _eventChannel(new Muduo::Channel(_eventFd, this)),
              _timerWheel(this)
        {
            // 给eventFd添加可读事件回调函数，读取eventFd事件通知次数
            _eventChannel->SetReadCallback(std::bind(&EventLoop::ReadEvent, this));
            // 启动eventFd的读事件监控
            _eventChannel->EnableRead();
        }
        ~EventLoop()
        {
        }

        // 判断将要执行的任务是否处于当前线程中，如果在则执行，不在则压入队列中
        void RunInLoop(const Functor &cb)
        {
            if (IsInLoop())
            {
                return cb();
            }
            QueueInLoop(cb);
        }
        // 将任务压入任务池中
        void QueueInLoop(const Functor &cb)
        {
            {
                // 加锁添加任务
                std::unique_lock<std::mutex> _lock(_mutex);
                _tasks.push_back(cb);
            }
            /* 唤醒有可能因为没有事件就绪，而导致的epoll阻塞---防止epoll模块中监控的连接上长时间没有事件触发，
            线程一直阻塞在等待epoll模型监控的描述符上有事件触发，会导致任务池中的任务长时间没有执行*/
            WeakUpEventFd();
        }
        // 用于判断当前线程是否是EventLoop对应的线程
        bool IsInLoop()
        {
            return _threadId == std::this_thread::get_id();
        }
        void AssertInLoop()
        {
            //判断是否为当前线程
            if(_threadId != std::this_thread::get_id())
            {
                abort();
            }
        }
        // 添加/修改描述符的事件监控
        void UpdateEvent(Muduo::Channel *channel)
        {
            _poller.UpdateEvent(channel);
        }
        // 移除描述符的监控
        void RemoveEvent(Muduo::Channel *channel)
        {
            _poller.ReMoveEvent(channel);
        }
        // 启动EventLoop：三步走：事件监控--> 就绪事件处理--->执行任务
        void Start()
        {
            while(1)
            { 
                // 1.事件监控；
                std::vector<Muduo::Channel *> actives;
                _poller.Poll(actives);
                // 2.事件处理；
                for (const auto &channel : actives)
                {
                    channel->HandleEvent();
                }
                // 3.执行任务
                RunAllTask();
            }
        }
        //添加定时任务
        void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc&cb)
        {
            _timerWheel.TimerAdd(id, delay,cb);
        }
        //刷新定时任务
        void TimerRefresh(uint64_t id)
        {
            _timerWheel.TimerRefresh(id);
        }
        //取消定时任务
        void TimerCancel(uint64_t id)
        {
            _timerWheel.TimerCancel(id);
        }
        //判断某个定时任务是否存在
        bool HasTimer(uint64_t id)
        {
            return _timerWheel.HasTimer(id);
        }
    private:
        // 执行任务队列中所有的任务
        void RunAllTask()
        {
            std::vector<Functor> functor;
            {
                // 在任意的地方都有可能往任务池中添加任务，所以将任务队列中任务加锁交换出来
                std::unique_lock<std::mutex> _lock(_mutex);
                // 加锁的时候去打印任务的数量
                _tasks.swap(functor);//这里的问题，任务队列中的任务交换给了自己，一直没有处理，导致的错误，
            }
            // 执行任务
            for (const auto &f : functor)
            {
                f();
            }
        }
        // 创建eventfd
        static int CreateEventFd()
        {
            int efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
            if (efd < 0)
            {
                LOGERROR("event fd create fail!");
                abort();
            }
            return efd;
        }
        // eventfd的读事件回调函数
        void ReadEvent()
        {
            uint64_t buf = 0;
            int ret = read(_eventFd, &buf, sizeof(buf));
            if (ret < 0)
            {
                // EINTR表示read操作被信号打断；EAGAIN表示无数据可读；
                if (errno == EINTR || EAGAIN)
                {
                    return;
                }
                LOGERROR("read eventfd fail!");
                abort();
            }
            return;
        }
        // 唤醒有可能因为没有事件就绪，而导致的epoll阻塞---其实就是给eventfd写入一个数据，让eventfd触发可读事件，那么epoll有事件就绪了就不会阻塞了
        void WeakUpEventFd()
        {
            uint64_t buf = 0;
            int ret = write(_eventFd, &buf, sizeof(buf));
            if (ret < 0)
            {
                if (errno == EINTR)
                {
                    return;
                }
                LOGERROR("write eventfd fail!");
                abort();
            }
        }

    private:
        std::thread::id _threadId;                     // 线程ID,这个是当前EventLoop对应的线程的ID
        int _eventFd;                                  // eventfd唤醒IO事件监控有可能导致的阻塞
        std::unique_ptr<Muduo::Channel> _eventChannel; // 对eventFd进行事件管理的Channel对象；
        Muduo::Poller _poller;                         // 进行所有描述符的事件监控；
        Muduo::TimerWheel _timerWheel;    //定时器
        std::vector<Functor> _tasks; // 任务池
        std::mutex _mutex;           // 实现任务池操作的线程安全
        
    };

    // 将当前连接的事件监控从epoll中移除
    void Muduo::Channel::Remove()
    {
        // done---调用EventLoop模块的接口来移除epoll中当前连接的事件监控；
        _loop->RemoveEvent(this);
    }
    // 将事件监控更新到epoll模型中
    void Muduo::Channel::Update()
    {
        _loop->UpdateEvent(this);
    }

    // 定时器中有个_timers成员，定时器信息的操作有可能在多个线程中进行，因此需要考虑线程安全问题
    // 如果不想加锁，就将所有对定时器的操作都放到同一个线程中来完成，保证了线程安全；
    //添加定时任务
    void Muduo::TimerWheel::TimerAdd(uint64_t id, uint32_t delay, TaskFunc taskCb)
    {
        _loop->RunInLoop(std::bind(&TimerWheel::TimerAddInLoop, this, id, delay, taskCb));
    }
    // 定时器中有个_timers成员，定时器信息的操作有可能在多个线程中进行，因此需要考虑线程安全问题
    // 如果不想加锁，就将所有对定时器的操作都放到同一个线程中来完成，保证了线程安全；
    //刷新定时任务
    void Muduo::TimerWheel::TimerRefresh(uint64_t id)
    {
        _loop->RunInLoop(std::bind(&TimerWheel::TimerRefreshInLoop, this, id));
    }
    // 定时器中有个_timers成员，定时器信息的操作有可能在多个线程中进行，因此需要考虑线程安全问题
    // 如果不想加锁，就将所有对定时器的操作都放到同一个线程中来完成，保证了线程安全；
    // 取消定时任务
    void Muduo::TimerWheel::TimerCancel(uint64_t id)
    {
        _loop->RunInLoop(std::bind(&TimerWheel::TimerCancelInLoop, this, id));
    }

    typedef enum 
    {
        DISCONNECTED,    //连接关闭状态
        CONNECTING,   //连接建立成功，待处理状态，比如设置回调函数，事件监控等
        CONNECTED,      //连接建立完成，各种设置已完成，可以通信的状态；
        DISCONNECTING   //待关闭状态---通信连接的接收发送缓冲区中还有数据需要发送或者处理；
    }ConnStatus;
    class Connection;
    using PtrConnection = std::shared_ptr<Muduo::Connection>;
    class Connection : public std::enable_shared_from_this<Connection>
    {       
    private:
        uint64_t _connId;  //通信连接的唯一ID，便于连接的管理和查找；
        int _sockfd; //通信连接的描述符
        //uint64_t _timerId;    //定时器ID，必须是唯一的，这块为了简化操作使用 _connId 作为定时器ID；
        bool _enableInactiveRelease = false;    //连接是否启动非活跃销毁的判断标志，默认为false；
        Muduo::EventLoop* _loop; //连接所关联的EventLoop;
        ConnStatus _status = CONNECTING; //通信连接的状态；
        Muduo::Socket _socket;  //套接字的操作管理
        Muduo::Channel _channel;    //连接事件的管理
        //当对端发送来的数据非常大的时候，socket的内核缓冲区一次放不下所有数据，如果没有接收缓冲区，不将数据从socket中拿到接收缓冲区中，
        //对端就无法将剩余的数据发送完毕，本次通信也就一直完不成；
        Muduo::Buffer _inBuffer;    //接收缓冲区---存放从socket中读取的数据；
        //如果不先将发送的数据放到发送缓冲区中直接通过socket发送，就会出现套接字写条件不具备的时候发送导致阻塞的问题；将要发送的数据放到发送
        //缓冲区中，等到套接字写事件触发后会自动调用回调函数对发送缓冲区中的数据进行发送；
        Muduo::Buffer _outBuffer;   //发送缓冲区---存放要发送给对端的数据；
        Muduo::Any _context; //协议上下文；

        /*下面这四个回调函数是让服务器模块来设置的，其实服务器模块的处理回调也是让组件使用者根据自己的业务需求设置*/
        //即就是组件使用者设置给服务器，当服务器获取到新连接后，服务器再设置给新连接；
        //换句话说这几个回调都是组件使用者使用的
        using ConnectedCallback = std::function<void(const PtrConnection&)>;
        using MessageCallback = std::function<void(const PtrConnection&, Muduo::Buffer*)>;
        using CloseCallback = std::function<void(const PtrConnection&)>;
        using AnyEventCallback = std::function<void(const PtrConnection&)>;
        ConnectedCallback _connectedCallback;   //通信连接建立的回调函数
        MessageCallback  _messageCallback;  //业务处理的回调函数
        CloseCallback _closedCallback;  //连接关闭后的回调函数
        AnyEventCallback _eventCallback;    //任意事件的回调函数

        /*组件内的连接关闭回调---由组件内设置，因为服务器组件内会把所有的连接管理起来，一旦某个连接要关闭了，就应该从管理的地方移除自己的信息*/
        CloseCallback _serverClosedCallback;

    private:
        /*五个channel的事件回调函数*/
        //描述符触发可读事件后调用的回调函数---接收socket上的数据放到接收缓冲区中，然后调用业务处理回调函数_message_callback进行业务处理
        void HandleRead()
        {
            char buf[65536];
            ssize_t ret = _socket.NonBlockRecv(buf, sizeof(buf));
            if(ret < 0)
            {
                //读取socket上的数据出错了，不能直接关闭连接，而是看一下该连接的发送和接收缓冲区中有没有数据待处理
                LOGERROR("read error!");
                return ShutdownInLoop();
            }
            else if(ret == 0)
            {
                //这里等于0表示的时没有读取到数据，而并不是连接断开了，连接断开了返回的是-1
                return;
            }

            //将数据放到接收缓冲区中
            _inBuffer.WriteAndPush(buf, ret);
            //如果接收缓冲区中有可读数据则调用业务回调函数进行业务处理
            if(_inBuffer.ReadAbleSize() > 0)
            {
                /*shred_from_this接口是从当前对象自身获取自身的shared_ptr管理对象，
                但是使用这个接口必须让当前类公有继承std::enable_shared_from_this<Connection>*/
                return _messageCallback(shared_from_this(), &_inBuffer);
            }
        }
        //描述符触发可写事件后调用的回调函数---将发送缓冲区中的数据进行发送
        void HandleWrite()
        {
            //_outBuffer中保存的数据就是要发送的数据
            ssize_t ret = _socket.NonBlockSend(_outBuffer.ReadPosition(), _outBuffer.ReadAbleSize());
            if(ret < 0)
            {
                //发送错误就该关闭连接，但是要先看发送缓冲区中是否有数据需要处理，有就处理,处理结束后就真正的关闭连接
                if(_inBuffer.ReadAbleSize() > 0)
                {
                    _messageCallback(shared_from_this(), &_inBuffer);
                }
                return Release();//实际的关闭连接
            }
            //千万不要忘记了，将读位置向后偏移，要不然发送缓冲区中的数据永远发送不完
            _outBuffer.MoveReadOffest(ret);

            if(_outBuffer.ReadAbleSize() == 0)
            {
                //发送缓冲区中没有数据了就关闭连接的写事件监控；
                _channel.DisableWrite();
                //如果当前是连接待关闭状态，则有数据，发送完数据释放连接，没有数据则直接释放连接
                if(_status == DISCONNECTING)
                {
                    //连接处于待关闭状态，并且发送缓冲区中没有数据可发送,就直接关闭连接
                    return Release();
                }
            } 
        }
        //描述符触发挂断(关闭)事件后调用的回调函数---对接收缓冲区中的数据处理后，描述符进行释放
        //这里的挂断是指用户主动关闭连接，那么发送缓冲区中即使有数据也无法发送；
        void HandleClose()
        {
            /*一旦连接挂断了，套接字就什么都干不了了，因此有数据待处理就处理一下，完毕关闭连接*/
            if(_inBuffer.ReadAbleSize() > 0)
            {
                _messageCallback(shared_from_this(), &_inBuffer);
            }
            Release();
        }
        //描述符触发错误事件后调用的回调函数---关闭连接
        void HandleError()
        {
            //有数据就处理一下，没有就直接关闭连接
            HandleClose();
        }
        //描述符触发任意事件后调用的回调函数---1、刷新连接的活跃度(延迟定时销毁任务)，2、调用组件使用者的任意事件回调
        void HandleEvent()
        {
            //1、刷新连接的活跃度(延迟定时销毁任务)
            if(_enableInactiveRelease == true)
            {
                //开启了定时销毁任务就刷新连接的活跃度
                _loop->TimerRefresh(_connId);
            }
            if(_eventCallback)
            {
                _eventCallback(shared_from_this());
            }
        }

        //为了保证线程安全，对连接的所有操作都要放到对应的EventLoop对应的线程当中执行
        //连接获取之后，所处的状态下要进行的各种设置(启动读事件监控，设置调用连接建立后的回调函数)
        void EstablishedInLoop()
        {
            //修改连接状态
            if(_status != CONNECTING)
            {
                LOGERROR("当前连接未处于待处理状态，不能对连接进行各种设置！");
                exit(-1);
            }
            _status = CONNECTED;//当前函数执行完毕，则连接进入已完成连接状态
            /*一旦启动读事件监控就有可能会立即触发读事件，如果这个时候启动了非活跃连接销毁，就会在事件触发后先刷新连接的活跃度；
            在启动非活跃连接的超时销毁的时候将连接超时销毁的任务添加到定时器中，如果将启动读事件监控的操作放到该类的构造函数中会
            出现还没有添加定时任务，但是去刷新连接的活跃度了，这样就出现了逻辑错误，是因为非活跃连接的超时销毁是在启动非活跃连接的超时销毁时添加
            到定时器中的，构造函数中启动读事件监控的时候还没有将非活跃连接的超时销毁添加到定时器中；所以启动读事件监控是在启动非活跃连接销毁之后*/ 
            //开启读事件监控
            _channel.EnableRead();  
            if(_connectedCallback)
            {
                _connectedCallback(shared_from_this());
            }
        }
        //发送数据，将数据放到发送缓冲区，启动写事件监控，并不是实际的发送接口
        void SendInLoop(Muduo::Buffer& buffer)
        {
            if(_status == DISCONNECTED)
            {
                return;
            }
            //1.将数据放到发送缓冲区
            _outBuffer.WriteBufferAndPush(buffer);
            //2.启动写事件监控
            if(_channel.WriteAble() == false)
            {
                _channel.EnableWrite();
            }
        }
        //关闭连接---提供给组件使用者的关闭接口，并不会实际关闭套接字，需要判断缓冲区中有没有数据待处理
        void ShutdownInLoop()
        {
            _status = DISCONNECTING;//设置连接为待关闭状态
            if(_inBuffer.ReadAbleSize() > 0)
            {
                if(_messageCallback)
                {
                    /*这里进行一次业务处理，不管接收缓冲区中的数据有没有处理完；因为有可能接收缓冲区中的数据不全，
                    导致上层不会对接收缓存区中的数据处理，那么接收缓冲区中就一直有数据 */
                    _messageCallback(shared_from_this(), &_inBuffer);
                }
            }
            //要么是写入数据的时候出错关闭，要么是没有待发送数据，直接关闭
            if(_outBuffer.ReadAbleSize() > 0)
            {
                if(_channel.WriteAble() == false)
                {
                    //发送缓冲区中有数据，但是可写事件监控没有开启，需要开启
                    _channel.EnableWrite();
                }    
            }
            if(_outBuffer.ReadAbleSize() == 0)
            {
                Release();
            }
        }
        //这个接口才是实际的连接释放接口
        void ReleaseInLoop()
        {
            //1.修改连接状态，置为DISCONNECTED
            _status = DISCONNECTED;
            //2.移除连接的事件监控
            _channel.Remove();
            //3.关闭描述符
            _socket.Close();
            //4.如果当前定时器队列中还有定时销毁任务，则取消任务
            if(_loop->HasTimer(_connId))
            {
                _loop->TimerCancel(_connId);
            }
            //5.调用关闭连接用户的回调函数---避免先移除服务器管理的连接信息导致Connection被释放，再去处理会出错，因此先调用用户的回调函数
            if(_closedCallback)
            {
                _closedCallback(shared_from_this());
            }
            //6.调用服务器组件内的关闭连接回调函数
            if(_serverClosedCallback)
            {
                _serverClosedCallback(shared_from_this());
            }
        }
        //启动非活跃连接的超时销毁,并定义多长时间无通信就是非活跃，添加定时任务
        void EnableInactiveReleaseInLoop(int sec)
        {
            //1.将判断标志 _enableInactiveRelease 置为true
            _enableInactiveRelease = true;
            //2.启动非活跃连接的超时销毁 --- 如果当前定时销毁任务已经存在，那么就刷新延迟一下即可，如果不存在定时销毁任务，则新增
            if(_loop->HasTimer(_connId))
            {
                _loop->TimerRefresh(_connId);
            }
            else
            {
                _loop->TimerAdd(_connId, sec, std::bind(&Connection::Release, this));
            }
        }
        //取消非活跃连接的超时销毁
        void CancelInactiveReleaseInLoop()
        {
            //1.将判断标志 _enableInactiveRelease 置为false
            _enableInactiveRelease = false;
            //取消已经存在的定时销毁任务
            if(_loop->HasTimer(_connId))
            {
                _loop->TimerCancel(_connId);
            }
        }
        //协议切换---重置上下文以及重置阶段性处理函数
        void UpgradeInLoop(const Muduo::Any& context, const ConnectedCallback& conn, const MessageCallback& msg, 
        const CloseCallback& closed, const AnyEventCallback& event)
        {
            _context=context;
            _connectedCallback = conn;
            _messageCallback = msg;
            _closedCallback = closed;
            _eventCallback = event;
        }
    public:
        Connection(Muduo::EventLoop* loop, uint64_t connId, int sockfd)
        :_connId(connId), _sockfd(sockfd), _loop(loop), _socket(_sockfd), _channel(_sockfd, loop)
        {
            //设置连接事件触发后的回调函数
            _channel.SetReadCallback(std::bind(&Connection::HandleRead, this));
            _channel.SetWriteCallback(std::bind(&Connection::HandleWrite, this));
            _channel.SetErrorCallback(std::bind(&Connection::HandleError, this));
            _channel.SetCloseCallback(std::bind(&Connection::HandleClose, this));
            _channel.SetEventCallback(std::bind(&Connection::HandleEvent,this));
        }
        ~Connection()
        {
            LOGDEBUG("release connection:%p", this);
        }
        //获取通信套接字的描述符
        int Fd()
        {
            return _sockfd;
        }
        //获取通信连接的ID
        int Id()
        {
            return _connId;
        }
        //判断连接是否处于CONNECTED 连接建立完成的状态
        bool Connected()
        {
            return _status == CONNECTED;
        }
        //设置协议上下文---连接建立完成时进行调用
        void SetContext(const Any& context)
        {
            _context = context;
        }
        //获取协议的上下文
        Muduo::Any* GetContext()
        {
            return &_context;
        }
        //设置通信连接建立的回调函数
        void SetConnectedCallback(const ConnectedCallback& cb)
        {
            _connectedCallback = cb;
        }
        //设置业务处理的回调函数
        void SetMessageCallback(const MessageCallback& cb)
        {
            _messageCallback = cb;
        }
        //设置关闭连接后的回调函数
        void SetCloseCallback(const CloseCallback& cb)
        {
            _closedCallback = cb;
        }
        //设置任意事件的回调函数
        void SetAnyEventCallback(const AnyEventCallback& cb)
        {
            _eventCallback = cb;
        }
        //设置组件内真正关闭连接的回调函数
        void SetServerCloseCallback(const CloseCallback& cb)
        {
            _serverClosedCallback = cb;
        }

        //连接建立就绪后，进行channel回调设置，启动读监控，调用 _connectedCallback
        void Established()
        {
            _loop->RunInLoop(std::bind(&Connection::EstablishedInLoop, this));
        }
        //发送数据，将数据放到发送缓冲区，启动写事件监控
        void Send(const char* data, size_t len)
        {
            /*外界传入的data，可能是个临时空间，我们现在只是把发送操作压入任务池中，有可能并没有被立即执行，
            因此有可能在执行的时候，data指向的空间有可能已经被释放了*/
            Buffer buf;
            buf.WriteAndPush(data, len);
            _loop->RunInLoop(std::bind(&Connection::SendInLoop, this, std::move(buf)));
        }
        //关闭连接---提供给组件使用者的关闭接口，并不会实际关闭套接字，需要判断缓冲区中有没有数据待处理
        void Shutdown()
        {
            _loop->RunInLoop(std::bind(&Connection::ShutdownInLoop, this));
        }
        void Release()
        {
            /*这里必须先添加到任务池中防止出现任务池中有关该连接的操作还没有执行完就在把连接直接给释放了，
            如果当前线程就是EventLoop对应的线程，使用RunInLoop的话就直接执行了ReleaseInLoop，这样连接就关闭了，
            但是有可能在任务池中还有该连接的一些操作没执行，就出错了，所以是将该操作直接添加到任务池中；*/
            _loop->QueueInLoop(std::bind(&Connection::ReleaseInLoop, this));
        }
        //启动非活跃连接的超时销毁,并定义多长时间无通信就是非活跃，添加定时任务
        void EnableInactiveRelease(int sec)
        {
            _loop->RunInLoop(std::bind(&Connection::EnableInactiveReleaseInLoop, this, sec));
        }
        //取消非活跃连接的超时销毁
        void CancelInactiveRelease()
        {
            _loop->RunInLoop(std::bind(&Connection::CancelInactiveReleaseInLoop, this));
        }
        //协议切换---重置上下文以及重置阶段性处理函数
        /*这个接口必须在EventLoop线程中立即执行，防备新的事件触发后，处理的时候，切换任务环没有被执行，则会导致数据使用了原始的协议处理了*/
        void Upgrade(const Muduo::Any& context, const ConnectedCallback& conn, const MessageCallback& msg, 
        const CloseCallback& closed, const AnyEventCallback& event)
        {
            _loop->AssertInLoop();
            _loop->RunInLoop(std::bind(&Connection::UpgradeInLoop, this, context, conn, msg, closed, event));
        }
    };

    class Acceptor
    {
    private:
        Muduo::Socket _socket;  //用于创建监听套接字
        Muduo::EventLoop* _loop;    //用于对监听套接字进行事件监控
        Muduo::Channel _channel;    //用于对监听套接字进行事件管理

        using AcceptCallback = std::function<void(int)>;
        AcceptCallback _acceptCallback; //获取新连接后，对新连接进行处理的回调函数
    
    private:
        //创建一个监听套接字
        int CreateServer(int port)
        {
            bool ret = _socket.CreateListenSocket(port);
            if(ret == false)
            {
                LOGFATAL("listen socket create fail!");
                abort();
            }
            return _socket.Fd();
        }

        //监听套接字读事件触发后的回调函数---获取新连接，调用_acceptCallback函数进行新连接的处理
        void HandleRead()
        {
            int newfd = _socket.Accept();
            if(newfd < 0)
            {
                return;
            }
            if(_acceptCallback)
            {
                _acceptCallback(newfd);
            }
        }
    public:
        /*我们都是先实例化一个Acceptor类对象，使用实例化的对象调用SetAcceptCallback接口设置回调函数，
        此时就出现了先启动新连接的读事件监控再设置回调函数的错误逻辑不能将启动读事件监控，放到构造函数中，
        必须在设置回调函数之后，再去启动读事件监控，否则又可能造成启动监控后，立即有事件触发，事件触发后处理的时候，
        回调函数还没有设置，导致新连接得不到处理，且资源泄露;*/
        Acceptor(Muduo::EventLoop* loop, int port)
        :_socket(CreateServer(port)), _loop(loop), _channel(_socket.Fd(), _loop)
        {
            //设置监听套接字读事件的回调函数
            _channel.SetReadCallback(std::bind(&Acceptor::HandleRead, this));
        }
        ~Acceptor()
        {}
        //设置获取新连接后调用的回调函数
        void SetAcceptCallback(const AcceptCallback& cb)
        {
            _acceptCallback = cb;
        }
        void Listen()
        {
            //启动监听套接字的读事件监控
            _channel.EnableRead();
        }
    };

    class LoopThread
    {
    private:
        /*锁和条件变量是用于实现 _loop获取的同步关系，避免线程创建了但是EventLoop对象 _loop还没有实例化之前去获取 _loop*/
        std::mutex _mutex;  //互斥锁，用于实现同步关系
        std::condition_variable _cond;  //条件变量，用于实现同步关系
        Muduo::EventLoop* _loop = nullptr; //EventLoop指针变量，这个对象需要在线程内部实例化
        std::thread _thread;    //EventLoop对应的线程

    private:
        //线程的入口函数---实例化EventLoop对象，唤醒 _cond上有可能阻塞的线程，并且开始运行EventLoop模块的功能, 即就是调用EventLoop对象的Start函数；
        void ThreadEntry()
        {
            Muduo::EventLoop loop;//为了让EventLoop对象的生命周期随着LoopThread
            {
                std::unique_lock<std::mutex> lock(_mutex);//加锁
                _loop = &loop;
                _cond.notify_all();//EventLoop对象实例化后，唤醒所有在条件变量 _cond上阻塞等待的线程
            }
            loop.Start();
        }
    public:
        //创建线程，设定线程入口函数
        LoopThread()
            :_loop(nullptr), _thread(&LoopThread::ThreadEntry, this)
        {}
        ~LoopThread()
        {}
        //外界获取当前线程关联的EventLoop对象指针
        Muduo::EventLoop* GetLoop()
        {
            Muduo::EventLoop* loop = nullptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                _cond.wait(lock, [&](){ return _loop != nullptr; });
                loop = _loop;
            }
            return loop;
        }
    };

    class LoopThreadPool
    {
    private:
        int _threadCount = 0;   //从属线程的数量
        int _nextLoopIndex = 0; //下一个EventLoop的下标
        Muduo::EventLoop* _baseLoop;    //主EventLoop，运行在主线程，从属线程数量为0，则所有的操作都在baseLoop中进行；
        std::vector<Muduo::LoopThread*> _threads;   //保存所有的LoopThread对象
        //从属线程数量大于0则从_loops中进行线程EventLoop分配；_threads中的LoopThread对象和_loops中的EventLoop一一对应
        std::vector<Muduo::EventLoop*> _loops;  

    public:
        LoopThreadPool(Muduo::EventLoop* baseLoop)
        :_baseLoop(baseLoop)
        {}
        //设置线程的数量
        void SetThreadCount(int count)
        {
            _threadCount = count;
        }
        //创建所有的从属线程
        void Create()
        {
            for(int i = 0; i < _threadCount; ++i)
            {
                _threads.push_back(new LoopThread());
                _loops.push_back(_threads[i]->GetLoop());
            }
        }
        //获取下一个EventLoop
        EventLoop* NextLoop()
        {
            //从属线程的数量为0时，所有的操作都在 _baseLoop中
            if(_threadCount == 0)
            {
                return _baseLoop;
            }
            _nextLoopIndex = (_nextLoopIndex + 1) % _threadCount;
            return _loops[_nextLoopIndex];
        }
    };

    class TcpServer
    {
        using Functor = std::function<void()>;
    private:
        uint64_t _nextId = 0;    //这是一个自动增长的连接ID, 用来给连接分配的
        int _port;  //服务器所要监听的端口
        int _timeout = 0;   //这个是非活跃连接的超时时间---多长时间不通信就属于非活跃连接
        bool _enableInactiveRelease = false;    //是否启动了非活跃连接超时销毁的判断标志        
        Muduo::EventLoop _baseLoop; //这个是主线程对应的EventLoop对象，负责监听套接字的事件处理
        Muduo::Acceptor _acceptor;  //这个是监听套接字的管理对象
        Muduo::LoopThreadPool _pool;    //这个是从属线程池；
        std::unordered_map<uint64_t, Muduo::PtrConnection> _conns;  //保存管理所有连接对应的shared_ptr对象，实现对新建连接的管理

        /*下面这四个回调函数是让服务器模块来设置的，其实服务器模块的处理回调也是让组件使用者根据自己的业务需求设置*/
        //即就是组件使用者设置给服务器，当服务器获取到新连接后，服务器再设置给新连接；
        //换句话说这几个回调都是组件使用者使用的
        using ConnectedCallback = std::function<void(const PtrConnection&)>;
        using MessageCallback = std::function<void(const PtrConnection&, Muduo::Buffer*)>;
        using CloseCallback = std::function<void(const PtrConnection&)>;
        using AnyEventCallback = std::function<void(const PtrConnection&)>;
        ConnectedCallback _connectedCallback;   //通信连接建立的回调函数
        MessageCallback  _messageCallback;  //业务处理的回调函数
        CloseCallback _closedCallback;  //连接关闭后的回调函数
        AnyEventCallback _eventCallback;    //任意事件的回调函数
    private:
        //为新连接构造一个Connection对象进行管理
        void NewConnection(int fd)
        {
            _nextId++;
            Muduo::PtrConnection conn(new Muduo::Connection(_pool.NextLoop(), _nextId, fd));
            conn->SetMessageCallback(_messageCallback);
            conn->SetConnectedCallback(_connectedCallback);
            conn->SetCloseCallback(_closedCallback);
            conn->SetAnyEventCallback(_eventCallback);
            //连接关闭后真正关闭连接的回调函数设置
            conn->SetServerCloseCallback(std::bind(&TcpServer::RemoveConnection, this, std::placeholders::_1));
            if(_enableInactiveRelease)
            {
                //启动非活跃连接的超时销毁
                conn->EnableInactiveRelease(_timeout);
            }
            //将连接的初始化任务加入到对应的EventLoop对象的任务队列中；任务：修改新连接的状态，开始新连接的读事件监控，调用连接创建成功时的回调函数
            conn->Established();
            //将新连接的Connection管理对象添加到_conns中
            _conns.insert({_nextId, conn});
            // LOGDEBUG("set a new connection---------");
        }
        void RemoveConnectionInLoop(const PtrConnection& conn)
        {
            //从_conns中删除要关闭连接对应的Connection管理对象
            int id = conn->Id();
            auto it = _conns.find(id);
            if(it != _conns.end())
            {
                _conns.erase(id);
            }
        }
        /*从管理Connection的 _conns中移除连接信息---当一个连接断开后，将_conns中的PtrConnection对象移除，才会真正的将连接关闭，_conns中
        对应的PtrConnection对象不移除，其他地方再怎么关闭连接都不是真正的关闭连接；这样可以防止出现线程执行了某个连接的关闭操作，但是在任务池中
        还存在该连接其他的操作任务，当执行任务池中该连接的其他操作时不会出现连接关闭了还在进行连接上数据读写的错误；*/
        void RemoveConnection(const PtrConnection& conn)
        {
            //为了线程安全问题，所有对连接的操作应该都在线程内部
            _baseLoop.RunInLoop(std::bind(&TcpServer::RemoveConnectionInLoop, this, conn));
        }
        //为了线程安全，所有的任务的执行都要放在连接对应的EventLoop对象中进行
        void RunAfterInLoop(const Functor & task, int delay)
        {
            _nextId++;
            _baseLoop.TimerAdd(_nextId, delay, task);
        }
    public:
        TcpServer(int port)
        :_port(port),
        _acceptor(&_baseLoop, _port),
        _pool(&_baseLoop)
        {
            //设置监听套接字的回调函数
            _acceptor.SetAcceptCallback(std::bind(&TcpServer::NewConnection, this, std::placeholders::_1));            
            //将监听套接字挂到主线程对应的EventLoop对象_baseLoop上开始读事件的监控
            _acceptor.Listen();
        }
        //设置线程池的数量
        void SetThreadCount(int count)
        {
            _pool.SetThreadCount(count);
        }
        //设置通信连接建立的回调函数
        void SetConnectedCallback(const ConnectedCallback& cb)
        {
            _connectedCallback = cb;
        }
        //设置业务处理的回调函数
        void SetMessageCallback(const MessageCallback& cb)
        {
            _messageCallback = cb;
        }
        //设置关闭连接后的回调函数
        void SetCloseCallback(const CloseCallback& cb)
        {
            _closedCallback = cb;
        }
        //设置任意事件的回调函数
        void SetAnyEventCallback(const AnyEventCallback& cb)
        {
            _eventCallback = cb;
        }
        //启动非活跃连接的超时销毁
        void EnableInactiveRelease(int timeout)
        {
            _enableInactiveRelease = true;
            _timeout = timeout;
        }
        //添加定时任务
        void RunAfter(const Functor & task, int delay)
        {
            _baseLoop.RunInLoop(std::bind(&TcpServer::RunAfterInLoop, this, task, delay));
        }
        //启动TcpServer服务器
        void Start()
        {
            //创建线程池中的从属线程---创建从属线程的时候一定要在设置了线程数量之前否则会出现越界访问 _pool的错误
            _pool.Create();
            //启动epoll模型进行事件监控
            _baseLoop.Start();
        }
    };

    class NetWork
    {
    public:
        NetWork()
        {
            /*当连接断开的时候我们还继续进行数据的发送会触发SIGPIPE异常，这个异常会导致程序直接退出，我们通过signal
            接口将SIGPIPE信号忽略, 这样即使在连接断开后还继续发送数据，虽然会触发SIGPIPE异常，但是由于我们忽略了这个信号
            所以该信号就不会导致进程的退出*/
            LOGDEBUG("SIGPIPE INIT");
            signal(SIGPIPE, SIG_IGN);
        }
    };
    static NetWork nw;
}

#endif